# ๐Ÿ–ค 03. ์ŠคํŠธ๋ฆผ (Stream) | ํŠน์ง• | ์ค‘๊ฐ„์—ฐ์‚ฐ | ์ตœ์ข…์—ฐ์‚ฐ

๐Ÿ˜ Stream์€ ์ž๋ฐ” 8 API ์—์„œ ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ด๋‹ค. ๋ฐ์ดํ„ฐ ์ปฌ๋ ‰์…˜ ๋ฐ˜๋ณต์„ ๋ฉ‹์ง€๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋ฉฐ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๋ฐ์ดํ„ฐ๋ฅผ ํˆฌ๋ช…ํ•˜๊ฒŒ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด์ž !

# ๐Ÿฝ๏ธ Dish ํด๋ž˜์Šค

package javaStudy.mda04;

public class Dish {

    String name;

    int calories;

    public Dish(String name, int calories) {
        this.name = name;
        this.calories = calories;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCalories() {
        return calories;
    }

    public void setCalories(int calories) {
        this.calories = calories;
    }

    @Override
    public String toString() {
        return "Dish{" +
                "name='" + name + '\'' +
                ", calories=" + calories +
                '}';
    }
}
package javaStudy.mda04;

import java.util.Arrays;
import java.util.List;

public class StreamTest {

    public static void main(String[] args) {
        List<Dish> dishList = Arrays.asList(
                new Dish("fish", 200),
                new Dish("candy", 50),
                new Dish("pasta", 500)
        );
    }
}

์ด์ œ ์ ‘์‹œ ๋ชฉ๋ก์„ ๋งŒ๋“ค์–ด์„œ ์ €์นผ๋กœ๋ฆฌ์ธ ์Œ์‹์˜ ์ด๋ฆ„์„ ๋ฝ‘์•„๋‚ด๋ณด์ž.

# ๐Ÿ’Ž ๊ธฐ์กด ์ฝ”๋“œ (JAVA 7)

// ์ €์นผ๋กœ๋ฆฌ ์Œ์‹ ๋ถ„๋ฅ˜
List<Dish> lowCaloricDishes = new ArrayList<>();
for (Dish dish : dishList) {
    if (dish.getCalories() < 400) {
        lowCaloricDishes.add(dish);
    }
}

// ์ต๋ช… ํด๋ž˜์Šค๋กœ ์š”๋ฆฌ ์ •๋ ฌ
// [Dish{name='candy', calories=50}, Dish{name='fish', calories=200}]
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
    @Override
    public int compare(Dish o1, Dish o2) {
        return Integer.compare(o1.getCalories(), o2.getCalories());
    }
});

// ์ •๋ ฌ๋œ ๋ฆฌ์ŠคํŠธ ์ฒ˜๋ฆฌํ•˜์—ฌ ์ด๋ฆ„ ์„ ํƒ
// [candy, fish]
List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish dish : lowCaloricDishes) {
    lowCaloricDishesName.add(dish.getName());
}

# ๐Ÿ’Ž ์ตœ์‹  ์ฝ”๋“œ (JAVA 8)

// [candy, fish]
List<String> lowCaloricDishesName2 =
                dishList.stream()
                .filter(d -> d.getCalories() < 400)
                .sorted(Comparator.comparing(Dish::getCalories))
                .map(Dish::getName)
                .collect(toList());

.. ์—„์ฒญ ๊น”๋”ํ•˜๊ธด ํ•˜๋‹ค.

# ๐Ÿฝ๏ธ ์ƒˆ๋กœ์šด Dish ํด๋ž˜์Šค

์•ž์œผ๋กœ๋Š” ์•„๋ž˜ Dish ํด๋ž˜์Šค์™€ menu ๋ฅผ ์ฃผ์š” ์˜ˆ์ œ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.

package javaStudy.mda04;

public class Dish {

    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {
        MEAT,
        FISH,
        OTHER
    }

    @Override
    public String toString() {
        return "Dish{" +
                "name='" + name + '\'' +
                ", vegetarian=" + vegetarian +
                ", calories=" + calories +
                ", type=" + type +
                '}';
    }
}
package javaStudy.mda04;

import java.util.Arrays;
import java.util.List;

public class MainMethod2 {

    public static List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH)
    );

    public static void main(String[] args) {

    }
}

# ๐Ÿ’Ž ์ŠคํŠธ๋ฆผ์˜ ํŠน์ง•

// [pork, beef, chicken]
List<String> threeHighCaloricDishnames =
            menu.stream()
            .filter(dish -> dish.getCalories() > 300)
            .map(Dish::getName)
            .limit(3)
            .collect(toList());

์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜๋Š” menu์— stream ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ŠคํŠธ๋ฆผ์„ ์–ป์—ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์—ฐ์†๋œ ์š”์†Œ๋ฅผ ์ŠคํŠธ๋ฆผ์— ์ œ๊ณตํ•œ๋‹ค.

๋‹ค์Œ์œผ๋กœ ์ŠคํŠธ๋ฆผ์— filter map limit collect๋กœ ์ด์–ด์ง€๋Š” ์ผ๋ จ์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ์„ ์ ์šฉํ•œ๋‹ค.

์ด๋•Œ, collect๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์—ฐ์‚ฐ์€ ์„œ๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ˜•์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ collect ์—ฐ์‚ฐ์œผ๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

collect๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” menu์—์„œ ๋ฌด์—‡๋„ ์„ ํƒ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋„ ์—†๋‹ค.

# ๐Ÿ’Ž ์ค‘๊ฐ„์—ฐ์‚ฐ

์—ฐ์‚ฐ ํ˜•์‹ ๋ฐ˜ํ™˜ ํ˜•์‹ ์—ฐ์‚ฐ์˜ ์ธ์ˆ˜ ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ
filter ์ค‘๊ฐ„ ์—ฐ์‚ฐ Stream<T> Predicate<T> T -> boolean
map ์ค‘๊ฐ„ ์—ฐ์‚ฐ Stream<R> Function<T, R> T -> R
limit ์ค‘๊ฐ„ ์—ฐ์‚ฐ Stream<T> - -
sorted ์ค‘๊ฐ„ ์—ฐ์‚ฐ Stream<T> Comparator<T> (T, T) -> int
distinct ์ค‘๊ฐ„ ์—ฐ์‚ฐ Stream<T> - -

# ๐Ÿ’Ž ์ตœ์ข… ์—ฐ์‚ฐ

์—ฐ์‚ฐ ํ˜•์‹ ๋ฐ˜ํ™˜ ํ˜•์‹ ๋ชฉ์ 
forEach ์ตœ์ข… ์—ฐ์„  void ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์š”์†Œ๋ฅผ ์†Œ๋น„ํ•˜๋ฉด์„œ ๋žŒ๋‹ค๋ฅผ ์ ์šฉํ•œ๋‹ค.
count ์ตœ์ข… ์—ฐ์‚ฐ long(generic) ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
collect ์ตœ์ข… ์—ฐ์‚ฐ - ์ŠคํŠธ๋ฆผ์„ ๋ฆฌ๋“€์Šคํ•ด์„œ ๋ฆฌ์ŠคํŠธ, ๋งต, ์ •์ˆ˜ ํ˜•์‹์˜ ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ ๋‹ค.

# Reference


๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜ (ํ•œ๋น›๋ฏธ๋””์–ด)

Last Updated: 3/8/2024, 5:46:31 AM